<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
   <div id="box">

   </div>
</body>

<script>
    // const promise = new Promise(function(resolve,resject) {
    //     if(/*异步操作成功*/) {
    //         resolve(value)
    //     } else {
    //         resject(error)
    //     }
     
    // })
    // function timeOut (ms) {
    //     return new Promise((resolve,resject) => {
    //         setTimeout(resolve, ms,'done');
    //     })
    // }
    // timeOut(100).then(res => {
    //     console.log(res)
    // })


    //二、 Promise 绑定后就会立即执行
    // let promise = new Promise((resolve,resject) => {
    //     console.log('Promise')
    //     resolve('11111')
    // })
    // promise.then(res => {
    //     console.log(res)
    //     console.log('hi i`am Promise ')
    // })
    // console.log('Hi! see me')

    // 三、Promise 异步加载图片例子
    // function loadImagesAsync (url) {
    //     return new Promise( function (resolve,resject) {
    //         const image  = new Image(100,100)
    //         image.onload = function() {
    //             resolve(image)
    //         }
    //         image.onerror  = function() {
    //             resject(new Error(`could not load image at ${url}`))
    //         }
    //         image.src = url
    //     })
    // }
    // loadImagesAsync('http://img.private.nsfxxkj.com/icon/2020/08/28/15986139848040.png').then(res => {
    //     console.log(res)
    //     let box = document.getElementById('box')
    //     box.appendChild(res)
    // })
    // .catch(err => {
    //     console.log(err)
    // })
    
    // 四、Promise对象实现的Ajax的操作例子
    // const getJSON = function(url) {
    //     const promise = new Promise( function(resolve,resject) {
    //         const handler = function() {
    //             if(this.readyState !== 4) {
    //                 return
    //             }
    //             if(this.status === 200) {
    //                 resolve(this.response)
    //             } else {
    //                 resject(new Error(this.statusText))
    //             }
    //         };
    //         const client = new XMLHttpRequest();
    //         client.open("GET", url);
    //         client.onreadystatechange = handler;
    //         client.responseType = "json";
    //         client.setRequestHeader("Accept", "application/json");
    //         client.send();
    //     });
    //     return Promise
    // }
    // getJSON("/posts.json").then(function(json) {
    //     console.log('Contents: ' + json);
    // },function(error) {
    //     console.error('出错了',error);
    // });

    // resolve函数的参数除了正常的值以外，还可能是另一个 Promise 实例
    // const p1 = new Promise( function(resolve,resject) {
    //     setTimeout(()=> resject(new Error('fail')),3000)
      
    // })
    // const p2 = new Promise(function(resolve,resject) {
    //    setTimeout(()=> resolve(p1),1000)
    // })
    // p2.then(res => {
    //     console.log(res)
    // })
    // .catch(error => {
    //     console.log(error)
    // })
    // 注意，调用resolve或reject并不会终结 Promise 的参数函数的执行
    // new Promise((resolve,resject) => {
    //     resolve(1)
    //     console.log(2)
    // })
    // .then(res => {
    //     console.log(res)
    // })
    // // 防止出现意外应该return出去
    // new Promise((resolve,resject) => {
    //    return  resolve(1)
    //     console.log(2)
    // })
    // .then(res => {
    //     console.log(res)
    // })


    // Promise.prototype.finally()  // f 爱 那 力 
    // 无论promise怎样都会执行 ES2018引入
    // const p = new Promise(function(resolve,resject) {
    //     return resolve(111)
    // })
    // p.then(res => console.log(res))
    // .finally(f => console.log('finally'))
    // 实现一个  Promise.prototype.finally()
    // Promise.prototype.finally = function(callback) {
    //     const p = this.constructor;
    //     return this.then(
    //         value => p.resolve(callback()).then(() => value),
    //         reason => p.resject(callback()).then(() => { throw reason})
    //     )
    // }

    // Promise.resolve() 时需要将现有对象转为 Promise 对象，Promise.resolve()方法就起到这个作用。
    // const jsPromise = promise.resolve('foo')
    // // 等价于
    // const newPromise = new Promise( function(resolve) {
    //     resolve('foo')
    // })
    // Promise.resolve()方法的参数分成四种情况。
    // （1）参数是一个 Promise 实例
        // 如果参数是 Promise 实例，那么Promise.resolve将不做任何修改、原封不动地返回这个实例
    // （2）参数是一个thenable对象
        // let thenable = {
        //     then: function(resolve,resject) {
        //         resolve(42)
        //     }
        // }
        // let p1 = new Promise (resolve => { resolve(thenable) })
        // p1.then(res => console.log(res))
        // Promise.resolve()方法会将这个对象转为 Promise 对象，然后就立即执行thenable对象的then()方法
     // （3）参数不是具有then()方法的对象，或根本就不是对象,会直接执行resolve,并且将参数转化为Promise
        //  const p = Promise.resolve('hello')
        //  p.then(res => console.log(res))
    // （4）不带有任何参数
            // 所以，如果希望得到一个 Promise 对象，比较方便的方法就是直接调用
            // const p = Promise.resolve()
            // p.then(res => ...)
            // 需要注意的是，立即resolve()的 Promise 对象，是在本轮“事件循环”（event loop）的结束时执行，而不是在下一轮“事件循环”的开始时。
            // setTimeout(function() {
            //     console.log('three')
            // },0)
            // Promise.resolve().then( res=> console.log('two'))
            // console.log('one')

    // 应用
    // 加载图片,可以将加载图片写成一个Promise,一旦图片加载完成,Promise的状态就发生改变
    // const PreloadImage = function(path) {
    //     return new Promise((resolve,reject)=> {
    //         // const image = new Image();
    //         // image.onload = () => {
    //         //     resolve(image)
    //         // }
    //         // image.onerror = () => {
    //         //     throw new Error('图片加载错误')
    //         // }
    //         // image.src = path
    //         const image = new Image();
    //         image.onload  = resolve;
    //         image.onerror = reject;
    //         image.src = path;
    //     } ) 
          
        
    // }
    // PreloadImage('http://img.private.nsfxxkj.com/icon/2020/11/24/16061829334357.png').then(res => {
    //         console.log(res)
    // })

    // Promise.try()
    // const f = () => console.log('now')
    // Promise.resolve().then(f)
    // console.log('next')


    // 么有没有一种方法，让同步函数同步执行，异步函数异步执行，并且让它们具有统一的 API 呢？回答是可以的，并且还有两种写法。第一种写法是用async函数来写。
    // const f = () => console.log('now');
    // (async () => f())();
    // console.log('next')
        
    // 函数递归
    // function factorial(n) {
    // if (n === 1) return 1;
    // return n * factorial(n - 1);
    // }

    // console.log(  factorial(100000000000)) // 120
    
    // // 改写为尾递归
    // function weiFac(n,total = 1) {
    //     if(n == 1) return total
    //     return weiFac( n-1 ,n* total  )
    // }
    // console.log(weiFac(1000))

//     function Fibonacci (n) {
//   if ( n <= 1 ) {return 1};

//   return Fibonacci(n - 1) + Fibonacci(n - 2);
// }
// console.log(Fibonacci(10))
// console.log(Fibonacci(100))
// console.log(Fibonacci(500))
// Fibonacci(10) // 89
// Fibonacci(100) // 超时
// Fibonacci(500) // 超时
// function Fibonacci2 (n , ac1 = 1 , ac2 = 1) {
//   if( n <= 1 ) {return ac2};

//   return Fibonacci2 (n - 1, ac2, ac1 + ac2);
// }
// console.log(Fibonacci2(10))
// console.log(Fibonacci2(100))
// console.log(Fibonacci2(500))
// Fibonacci2(100) // 573147844013817200000
// Fibonacci2(1000) // 7.0330367711422765e+208
// Fibonacci2(10000) // Infinity

// 红绿灯问题
function red() {
    console.log('red')
}
function green() {
    console.log('green')
}
function yellow() {
    console.log('yellow')
}

// 利用.then 和 递归实现
var light = function(timer,cb) {
    return new Promise(  (resolve,reject) => {
        setTimeout(function() {
            cb()
            resolve('一闪一闪')
        },timer)
    })
}

 // Promise.resolve() 等价于 new Promise(resolve => resolve())  
var step  = function() {
    Promise.resolve().then((res) => {
        console.log(res)
      return  light(3000,red)
    })
    .then(() => {
        return light(2000,green)
    })
    .then(() => {
        return  light(1000,yellow)
    })
    .then(() => {
        step()
    })
}
step()
let p1 = new Promise((resolve,reject) => {
    let num =2
    if(num ==1) {
        resolve({name:'地卢克'})
    } else {
        resolve({name:'1'})
    }
  

}) 
let p2 = Promise.resolve({name:'wendi'})

// Promise.all ，执行多个Promise，任意一个Promise出现错误Promise.all就会执行.catch(),只有所有都执行resolve成功才会走then
Promise.all([p1,p2])
.then(([x,y]) => {
//    const {name} = x
    console.log(x)
    console.log(y)
//     const {name:f} = y
//    console.log(name,f)
})
// .catch(
//     console.log('出错了')
// )

console.log( +new Date())
</script>

</html>                             